package com.maptool.map;

import android.util.Log;

import com.esri.arcgisruntime.geometry.AngularUnit;
import com.esri.arcgisruntime.geometry.AngularUnitId;
import com.esri.arcgisruntime.geometry.AreaUnit;
import com.esri.arcgisruntime.geometry.AreaUnitId;
import com.esri.arcgisruntime.geometry.GeodeticCurveType;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.GeometryEngine;
import com.esri.arcgisruntime.geometry.GeometryType;
import com.esri.arcgisruntime.geometry.ImmutablePartCollection;
import com.esri.arcgisruntime.geometry.LinearUnit;
import com.esri.arcgisruntime.geometry.LinearUnitId;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.PointCollection;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.geometry.Polyline;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.mapping.view.SketchCreationMode;
import com.esri.arcgisruntime.mapping.view.SketchEditor;
import com.esri.arcgisruntime.mapping.view.SketchGeometryChangedEvent;
import com.esri.arcgisruntime.mapping.view.SketchGeometryChangedListener;
import com.esri.arcgisruntime.mapping.view.SketchStyle;
import com.maptool.config.MapConfig;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 图斑平移
 */
public class GeometryMove {

    private static GeometryMove instance;

    //使用单例避免静态便量内存泄漏风险
    public static GeometryMove getInstance() {
        if (instance == null) {
            instance = new GeometryMove();
        }
        return instance;
    }


    private SketchEditor mainSketchEditor;
    private SketchStyle sketchStyle;//以前的样式
    private Geometry optNewGeomety;//记录移动的地块
    private Geometry tranGeometry;//记录移动的老地块
    private GraphicsOverlay mHighlightGraphicsOverlay;
    private MapView mapView;
    private GeometryChangedListene geometryChangedListene;

    /**
     * 平移地块
     */
    public void moveGeometry(MapView mMapView, Geometry moveGeometry) throws Exception {
        tranGeometry = moveGeometry;
        mapView = mMapView;

        mainSketchEditor = mMapView.getSketchEditor();
        if (mainSketchEditor == null) {
            mainSketchEditor = new SketchEditor();
        } else {
            sketchStyle = mMapView.getSketchEditor().getSketchStyle();
        }
        mainSketchEditor.setSketchStyle(MapConfig.getTtansparentSketchStyle());
        mMapView.setSketchEditor(mainSketchEditor);
        mainSketchEditor.start(SketchCreationMode.FREEHAND_LINE);
        //加载单个图斑高亮显示图层
        mHighlightGraphicsOverlay = new GraphicsOverlay();
        mapView.getGraphicsOverlays().add(mHighlightGraphicsOverlay);

        geometryChangedListene = new GeometryChangedListene();

        mainSketchEditor.addGeometryChangedListener(geometryChangedListene);
    }


    /**
     * 获取移动后的图斑
     *
     * @return
     */
    public Geometry getMoveGeometry() throws Exception {
        closeMoveGeometry();
        if (optNewGeomety != null) {
            return optNewGeomety;
        } else {
            return null;
        }
    }

    /**
     * 移动图斑关闭
     */
    public void closeMoveGeometry() throws Exception {
        mainSketchEditor.stop();
        mHighlightGraphicsOverlay.getGraphics().clear();
        if (sketchStyle != null) {
            mainSketchEditor.setSketchStyle(sketchStyle);
        }
        if (geometryChangedListene != null) {
            mainSketchEditor.removeGeometryChangedListener(geometryChangedListene);
        }
    }

    public class GeometryChangedListene implements SketchGeometryChangedListener {
        @Override
        public void geometryChanged(SketchGeometryChangedEvent sketchGeometryChangedEvent) {
            if (mainSketchEditor.getSketchCreationMode() == SketchCreationMode.FREEHAND_LINE) {

                Polyline polyline = (Polyline) mainSketchEditor.getGeometry();
                Iterable<Point> partsAsPoints = polyline.getParts().getPartsAsPoints();
                List<Point> listPoint = new ArrayList<>();

                for (Point point : partsAsPoints) {
                    listPoint.add(point);
                }
                if (listPoint.size() > 0) {
                    /**
                     * 1、拿出画的流状线的最后一个点坐标
                     */
                    Point clickPoint = listPoint.get(listPoint.size() - 1);


                    /**
                     * 计算需要移动图形的中心点坐标与流状线最后一个坐标的方位角
                     * */
                    double azimuth1 = GeometryEngine.distanceGeodetic(tranGeometry.getExtent().getCenter(), clickPoint,
                            new LinearUnit(LinearUnitId.METERS), new AngularUnit(AngularUnitId.DEGREES),
                            GeodeticCurveType.GREAT_ELLIPTIC).getAzimuth1();
                    PointCollection points = new PointCollection(mapView.getSpatialReference());
                    points.add(clickPoint);
                    points.add(tranGeometry.getExtent().getCenter());
                    Polyline polylineLength = new Polyline(points);
                    /**
                     * 计算需要移动图形的中心点坐标与流状线最后一个坐标的距离
                     * */
                    double length = GeometryEngine.lengthGeodetic(polylineLength, new LinearUnit(LinearUnitId.METERS), GeodeticCurveType.GREAT_ELLIPTIC);
                    // 输出滑动距离和方位角
                    Log.e("滑动距离", length + "");
                    /**
                     * 获取需要移动的面要素的所有点
                     */
                    ImmutablePartCollection parts = null;
                    List<Point> listPolygon = new ArrayList<>();
                    boolean polygonTaget = false;
                    if (tranGeometry.getGeometryType() == GeometryType.POLYGON) {
                        Polygon polygon = (Polygon) tranGeometry;
                        parts = polygon.getParts();
                        polygonTaget = true;
                    } else if (tranGeometry.getGeometryType() == GeometryType.POLYLINE) {
                        Polyline polygon = (Polyline) tranGeometry;
                        parts = polygon.getParts();
                        polygonTaget = false;
                    } else if (tranGeometry.getGeometryType() == GeometryType.POINT) {
                        Point point = (Point) tranGeometry;
                        listPolygon.add(point);
                        polygonTaget = false;
                    }
                    if (parts != null) {
                        if (parts.size() > 1 && polygonTaget) {
                            List<List<Point>> AllListPolygon = new ArrayList<>();
                            for (int i = 0; i < parts.size(); i++) {
                                Iterable<Point> points1 = parts.get(i).getPoints();
                                for (Point point : points1) {
                                    listPolygon.add(GeometryEngine.moveGeodetic(point, length, new LinearUnit(LinearUnitId.METERS),
                                            azimuth1, new AngularUnit(AngularUnitId.DEGREES), GeodeticCurveType.GEODESIC));
                                }
                                AllListPolygon.add(listPolygon);
                            }
                            List<Geometry> listGeometry = new ArrayList<>();
                            List<Double> doubles = new ArrayList<>();
                            for (List<Point> list : AllListPolygon) {
                                PointCollection polygonList = new PointCollection(mapView.getSpatialReference());
                                polygonList.addAll(list);
                                Polygon polygon1 = new Polygon(polygonList);
                                double geodetic = GeometryEngine.areaGeodetic(polygon1, new AreaUnit(AreaUnitId.SQUARE_METERS), GeodeticCurveType.SHAPE_PRESERVING);
                                listGeometry.add(polygon1);
                                doubles.add(geodetic);
                            }
                            optNewGeomety = GeometryEngine.union(listGeometry);
                            Double max = Collections.max(doubles);
                            int i = doubles.indexOf(max);
                            for (int j = 0; j < listPolygon.size(); j++) {
                                if (i != j) {
                                    optNewGeomety = GeometryEngine.difference(optNewGeomety, listPolygon.get(j));
                                }
                            }
                        } else {
                            Iterable<Point> partsAsPointsPolygon = parts.getPartsAsPoints();
                            for (Point point : partsAsPointsPolygon) {
                                listPolygon.add(point);
                            }
                        }
                        /**
                         * 需要移动的面要素的所有点向上面计算的方位角，距离整体移动
                         */
                        List<Point> list = GeometryEngine.moveGeodetic(listPolygon, length, new LinearUnit(LinearUnitId.METERS),
                                azimuth1, new AngularUnit(AngularUnitId.DEGREES), GeodeticCurveType.GEODESIC);
                        PointCollection polygonList = new PointCollection(mapView.getSpatialReference());
                        polygonList.addAll(list);

                        if (tranGeometry.getGeometryType() == GeometryType.POLYGON) {
                            optNewGeomety = new Polygon(polygonList);
                        } else if (tranGeometry.getGeometryType() == GeometryType.POLYLINE) {
                            optNewGeomety = new Polyline(polygonList);
                        } else if (tranGeometry.getGeometryType() == GeometryType.POINT) {
                            optNewGeomety = list.get(0);
                        }
                    }
                    mHighlightGraphicsOverlay.getGraphics().clear();
                    MapConfig.highlightGeometry(optNewGeomety, mHighlightGraphicsOverlay);
                }
            }
        }
    }


}
